home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / other / pmdev / c / demos / dynamic.c < prev    next >
C/C++ Source or Header  |  2000-02-28  |  6KB  |  225 lines

  1. /*
  2.  *
  3.  * $VER: Dynamic.c 1.1 (05.09.98)
  4.  *
  5.  * Popup Menu example program
  6.  *
  7.  * ©1996-1998 Henrik Isaksson
  8.  * All Rights Reserved.
  9.  *
  10.  */
  11.  
  12. #include <intuition/intuition.h>
  13. #include <exec/memory.h>
  14.  
  15. #include <proto/intuition.h>
  16. #include <proto/exec.h>
  17.  
  18. #include <clib/alib_protos.h>
  19.  
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23.  
  24. #include <libraries/pm.h>
  25. #include <proto/pm.h>
  26.  
  27. struct IntuitionBase    *IntuitionBase;
  28. struct GfxBase        *GfxBase;
  29. struct PopupMenuBase    *PopupMenuBase;
  30.  
  31. struct Window *w;    // This window is only needed to find out when and where the menu should appear.
  32.             // The font in this window's rastport will be used for the menu.
  33.  
  34. BOOL was_called=FALSE;    // Just used to find out if the destructor is called.
  35.  
  36. struct PopupMenu * __saveds __asm SubConstructFunc(register __a0 struct Hook *hook,
  37.                      register __a2 struct PopupMenu *selected, register __a1 APTR *handle)
  38. {
  39.     struct PopupMenu *newpm, *itm;
  40.     char bfr[128];
  41.     int i;
  42.     BOOL stop=FALSE;
  43.  
  44.     // Don't try to open windows, requesters or print text from this
  45.     // hook, wich is called while the menu is still open.
  46.     // The display might be locked!
  47.  
  48.     newpm=PM_MakeMenu(
  49.         itm=PMItem("(loading...)"),        PM_ID,    300,    PM_Disabled, TRUE, PMEnd,
  50.     PMEnd;        
  51.  
  52.     if(newpm) {
  53.         if(selected->Sub) {
  54.             // We don't have to worry about freeing the new menu,
  55.             // as it will be freed automatically. But we do have
  56.             // to take care of the old menu, since the library
  57.             // won't know it exists.
  58.             PM_FreePopupMenu(selected->Sub);
  59.         }
  60.         selected->Sub=newpm;
  61.  
  62.         PM_AbortHook(*handle);
  63.         Delay(50);
  64.  
  65.         PM_RemoveMenuItem(newpm, itm);
  66.  
  67.         //
  68.         // We can also add items to a previously created menu
  69.         //
  70.         PM_InsertMenuItem(newpm,
  71.             PM_Insert_Last, TRUE,
  72.             PM_Insert_Item,    PM_MakeItem(PM_Title, "These items have been added", TAG_DONE),
  73.             PM_Insert_Item,    PM_MakeItem(PM_Title, "to the end of the menu!", TAG_DONE),
  74.             PM_Insert_Item,    PM_MakeItem(PM_Title, "---------------- This item will be removed... ----------------", PM_ID, 100, TAG_DONE),
  75.             TAG_DONE);
  76.  
  77.         //
  78.         // Insert before an item
  79.         // The menu must have a 'header' (an invisible item at
  80.         // the top) for this to work reliably.
  81.         //
  82.         PM_InsertMenuItem(newpm,
  83.             PM_Insert_BeforeID, 100,
  84.             PM_Insert_Item,    PM_MakeItem(PM_Title, "This item has been inserted.", TAG_DONE),
  85.             TAG_DONE);
  86.  
  87.         //
  88.         // Insert after an item
  89.         //
  90.         PM_InsertMenuItem(newpm,
  91.             PM_Insert_AfterID,    100,
  92.             PM_Insert_Item,    PM_MakeItem(PM_Title, ",,^..^,,", TAG_DONE),
  93.             TAG_DONE);
  94.  
  95.  
  96.         PM_AbortHook(*handle);    // update the menu and give the user a chance to see it...
  97.         Delay(50);
  98.  
  99.         //
  100.         // Let's remove that long item
  101.         //
  102.         PM_RemoveMenuItem(newpm, PM_FindItem(newpm, 100));
  103.  
  104.  
  105.         //
  106.         // Add a few more items, and check if the user wants to abort
  107.         //
  108.         for(i=0;i<10;i++) {
  109.             Delay(10);
  110.             PM_InsertMenuItem(newpm,
  111.                 PM_Insert_Last,    TRUE,
  112.                 PM_Insert_Item,    PM_MakeItem(PM_Title, "new item", TAG_DONE),
  113.                 TAG_DONE);
  114.             if(stop=PM_AbortHook(*handle)) break;
  115.         }
  116.     }
  117.  
  118.     if(!stop)
  119.         return selected->Sub;    // If you return NULL, no menu will be opened.
  120.     else
  121.         return NULL;
  122. }
  123.  
  124. void __saveds __asm SubDestructFunc(register __a0 struct Hook *hook,
  125.                      register __a2 struct PopupMenu *parent)
  126. {
  127.     // Don't try to open windows, requesters or print text from this
  128.     // hook, wich is called while the menu is still open.
  129.     // The display might be locked, and input definitely is.
  130.  
  131.     //
  132.     // Here you can do something with your item's userdata...
  133.     //
  134.     //    parent->Sub->UserData=0;
  135.     //
  136.     // ...or free the submenu, if you want to. Otherwise it will be free'd
  137.     // when you free the rest of the menu. If you decide to free the menu,
  138.     // remember to set parent->Sub to NULL.
  139.     // (maybe it's a very large menu, and you want to return the used mem)
  140.     //
  141.     //    PM_FreePopupMenu(parent->Sub);
  142.     //    parent->Sub=NULL;
  143.     //
  144.  
  145.     was_called=TRUE;    // Only to find out if this works...
  146. }
  147.  
  148. struct Hook SubConstruct;
  149. struct Hook SubDestruct;
  150.  
  151. struct PopupMenu *MakeTestMenu(void);
  152.  
  153. void main()
  154. {
  155.     struct IntuiMessage *im,imsg;
  156.     struct PopupMenu *p;
  157.     BOOL r=TRUE;
  158.  
  159.     SubConstruct.h_Entry=(HOOKFUNC)SubConstructFunc;
  160.     SubConstruct.h_Data=NULL;    // User Data - you can put anything you like to here.
  161.  
  162.     SubDestruct.h_Entry=(HOOKFUNC)SubDestructFunc;
  163.     SubDestruct.h_Data=NULL;    // User Data - you can put anything you like to here.
  164.  
  165.     PopupMenuBase=(struct PopupMenuBase *)OpenLibrary(POPUPMENU_NAME,POPUPMENU_VERSION);            // Open the library
  166.     if(PopupMenuBase) {
  167.         IntuitionBase=(struct IntuitionBase *)PopupMenuBase->pmb_IntuitionBase;    // We let popupmenu.library open the libraries we need
  168.         GfxBase=(struct GfxBase *)PopupMenuBase->pmb_GfxBase;            // They remain valid until the library is closed!
  169.  
  170.         p=MakeTestMenu(); // Declared at the end of this file.
  171.  
  172.         if(p) {
  173.             w=OpenWindowTags(NULL,    WA_IDCMP,    IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_VANILLAKEY,    // Open a little window
  174.                     WA_RMBTrap,    TRUE,
  175.                     WA_DragBar,    TRUE,
  176.                     WA_Width,    150,
  177.                     WA_Height,    100,
  178.                     WA_Left,    0,
  179.                     WA_Top,        100,
  180.                     WA_Title,    "Dynamic Menus",
  181.                     WA_CloseGadget,    TRUE,
  182.                     TAG_DONE);
  183.             if(w) {
  184.                 while(r) {
  185.                     WaitPort(w->UserPort);                        // Wait for a message
  186.                     while((im=(struct IntuiMessage *)GetMsg(w->UserPort))) {    // Get the message
  187.                         CopyMem(im,&imsg,sizeof(struct IntuiMessage));        // Copy the contents of it
  188.                         ReplyMsg((struct Message *)im);                // Reply the message
  189.  
  190.                         if(imsg.Class==IDCMP_MOUSEBUTTONS) {
  191.                             PM_OpenPopupMenu(w,
  192.                                 PM_Menu,        p,
  193.                                 TAG_DONE);
  194.                         }
  195.                         if(imsg.Class==IDCMP_CLOSEWINDOW) r=FALSE;        // See if the user wants to quit
  196.                     }
  197.                 }
  198.                 printf("The destructor hook was %scalled!\n", was_called?"":"NOT ");
  199.                 CloseWindow(w);
  200.             } else printf("Window error!\n");
  201.             PM_FreePopupMenu(p);
  202.         } else printf("Menu error!\n");
  203.         CloseLibrary((struct Library *)PopupMenuBase);
  204.     }
  205. }
  206.  
  207. struct PopupMenu *MakeTestMenu()
  208. {
  209.     struct PopupMenu *p;
  210.  
  211.     p=PM_MakeMenu(
  212.         PMItem("Dynamic SubMenu"),
  213.             PM_SubConstruct,    &SubConstruct,
  214.             PM_SubDestruct,        &SubDestruct,
  215.             PMSimpleSub,
  216.                 PMInfo("This won't work unless"),    End,    // this will be shown if the demo doesn't work
  217.                 PMInfo("you get version 7.50!"),    End,    // (maybe an old version of the library)
  218.             End,
  219.         End,
  220.         PMBar,    End,
  221.         PMItem("Quit"), End,
  222.     End;
  223.  
  224.     return p;
  225. }